package com.cyt.gen.utils;

import cn.org.rapid_framework.generator.GeneratorFacade;
import cn.org.rapid_framework.generator.GeneratorProperties;
import com.cyt.gen.model.vo.GeneratorVo;
import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author rong yuan
 * @date 2019/7/4 13:32
 */
public class GeneratorUtil {

    protected static final String jdbc_driver = "com.mysql.jdbc.Driver";
    protected static final String jdbc_url = "jdbc:mysql://111.38.169.218:8000/cyt_wechat";
    protected static final String jdbc_username = "root";
    protected static final String jdbc_password = "123456";

    protected String tableName;
    protected String projectPath;
    protected String packageName;
    protected String moduleName;
    protected String entityName;
    protected String authorName;
    protected String moduleLogName;
    protected String classLogName;

    protected String outRootJava;
    protected String templateRootJava;
    protected String outRootController;
    protected String templateRootController;

    public GeneratorUtil(GeneratorVo generatorVo) {
        this.tableName = generatorVo.getTableName();
        this.projectPath = generatorVo.getProjectPath();
        this.packageName = generatorVo.getPackageName();
        this.moduleName = generatorVo.getModuleName();
        this.entityName = generatorVo.getEntityName();
        this.authorName = generatorVo.getAuthorName();
        this.moduleLogName = generatorVo.getModuleLogName();
        this.classLogName = generatorVo.getClassLogName();
    }

    public void generatorCode() throws Exception {

    }

    void deleteGeneratorCode() {
        List<File> fileList = new ArrayList<>();
        String basePath = projectPath + "cyt-" + packageName + "/src/main/java/com/cyt/" + moduleName;
        fileList.add(new File((basePath + "/service/impl/" + entityName + "ServiceImpl.java")));
        fileList.add(new File((basePath + "/service/impl")));
        fileList.add(new File((basePath + "/service/" + entityName + "Service.java")));
        fileList.add(new File((basePath + "/service")));
        fileList.add(new File((basePath + "/dao/" + entityName + "Dao.java")));
        fileList.add(new File((basePath + "/dao")));
        fileList.add(new File((basePath + "/model/po/" + entityName + ".java")));
        fileList.add(new File((basePath + "/model/po")));
        fileList.add(new File((basePath + "/model/vo/" + entityName + "Vo.java")));
        fileList.add(new File((basePath + "/model/vo")));
        fileList.add(new File((basePath + "/model")));
        fileList.add(new File((basePath)));
        basePath = projectPath + "cyt-" + packageName + "/src/main/resources/mapping/" + moduleName;
        fileList.add(new File((basePath + "/" + entityName + "Mapper.xml")));
        fileList.add(new File((basePath)));
        basePath = projectPath + "cyt-web/src/main/java/com/cyt/web/controller/" + moduleName;
        fileList.add(new File((basePath + "/" + entityName + "Controller.java")));
        fileList.add(new File((basePath)));
        basePath = projectPath + "cyt-web/src/main/webapp/WEB-INF/html/" + moduleName + "/" + entityName.replace(moduleName, "").toLowerCase();
        fileList.add(new File((basePath + "/" + Character.toLowerCase(entityName.charAt(0)) + entityName.substring(1) + "List.html")));
        fileList.add(new File((basePath + "/" + Character.toLowerCase(entityName.charAt(0)) + entityName.substring(1) + "Edit.html")));
        fileList.add(new File((basePath)));
        basePath = projectPath + "cyt-web/src/main/webapp/WEB-INF/html/" + moduleName;
        fileList.add(new File((basePath)));
        deleteFileOrDirectory(fileList);
    }

    private void deleteFileOrDirectory(List<File> fileList) {
        for (File file : fileList) {
            if (file.exists() && file.isFile()) {
                boolean result = file.delete();
                while (!result) {
                    if (file.exists()) {
                        System.gc();
                        result = file.delete();
                    }
                }
            }
        }
        for (File file : fileList) {
            if (file.exists() && file.isDirectory()) {
                File[] files = file.listFiles();
                if (files != null && files.length == 0) {
                    boolean result = file.delete();
                    while (!result) {
                        if (file.exists()) {
                            System.gc();
                            result = file.delete();
                        }
                    }
                }
            }
        }
    }

    void initGeneratorProperties() {
        GeneratorProperties.setProperty("jdbc_driver", jdbc_driver);
        GeneratorProperties.setProperty("jdbc_url", jdbc_url);
        GeneratorProperties.setProperty("jdbc_username", jdbc_username);
        GeneratorProperties.setProperty("jdbc_password", jdbc_password);
        GeneratorProperties.setProperty("java_typemapping.java.lang.Byte", "Integer");
        GeneratorProperties.setProperty("java_typemapping.java.lang.Short", "Integer");
        GeneratorProperties.setProperty("java_typemapping.java.lang.Integer", "Integer");
        GeneratorProperties.setProperty("java_typemapping.java.lang.Long", "Integer");
        GeneratorProperties.setProperty("java_typemapping.java.lang.Float", "Float");
        GeneratorProperties.setProperty("java_typemapping.java.lang.Double", "Double");
        GeneratorProperties.setProperty("java_typemapping.java.lang.String", "String");
        GeneratorProperties.setProperty("java_typemapping.java.sql.Date", "Date");
        GeneratorProperties.setProperty("java_typemapping.java.sql.Timestamp", "Date");
        GeneratorProperties.setProperty("tableComment", moduleLogName + "-" + classLogName);
        GeneratorProperties.setProperty("moduleLogName", moduleLogName);
        GeneratorProperties.setProperty("classLogName", classLogName);
        GeneratorProperties.setProperty("module", moduleName);
        GeneratorProperties.setProperty("entity", entityName);
        GeneratorProperties.setProperty("author", authorName);
    }

    void startGeneratorCode() throws Exception {
        GeneratorFacade generatorFacade;
        GeneratorProperties.setProperty("outRoot", outRootJava);
        generatorFacade = new GeneratorFacade();
        generatorFacade.getGenerator().setTemplateRootDir(templateRootJava);
        generatorFacade.generateByTable(tableName);
        GeneratorProperties.setProperty("outRoot", outRootController);
        generatorFacade = new GeneratorFacade();
        generatorFacade.getGenerator().setTemplateRootDir(templateRootController);
        generatorFacade.generateByTable(tableName);
    }

    void generatorCodeList(List<String> outFiles, List<String> templateFiles, String templatePath, Map<String, Object> dataModel) {
        for (int i = 0; i < outFiles.size(); i++) {
            String outFile = outFiles.get(i);
            String templateFile = templateFiles.get(i);
            this.generatorCode(outFile, templateFile, templatePath, dataModel);
        }
    }

    private void generatorCode(String outFile, String templateFile, String templatePath, Map<String, Object> dataModel) {
        try {
            File file = new File(outFile.substring(0, outFile.lastIndexOf("/")));
            boolean result = true;
            if (!file.exists() || !file.isDirectory()) {
                result = file.mkdirs();
            }
            if (result) {
                Configuration configuration = new Configuration();
                configuration.setDirectoryForTemplateLoading(new File(templatePath));
                Template template = configuration.getTemplate(templateFile, "UTF-8");
                if (template != null) {
                    template.process(dataModel, new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}